package com.vteba.utils.id;

import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.beans.factory.InitializingBean;

import com.vteba.utils.date.JodaTimeUtils;

/**
 * 主键生成器，默认yyyyMMddHHmmssSSS + 循环自增数字。
 * @author yinlei
 * @date 2014年10月15日 下午3:28:50
 */
public class IdsGenerator implements InitializingBean {
	private static String YMD = "yyyyMMddHHmmssSSS";
	private static int ID_START = 1000000;
	private static int SAFETY_VALVE = 8000000;
	
	private String format = YMD;
	private int start = ID_START;
	private int safetyValve = SAFETY_VALVE;
	private String prefix;
	
	private volatile AtomicInteger INTEGER = new AtomicInteger(1);
	
	/**
	 * 获取固定长度的id。格式是yyyyMMddHHmmssSSS + 7位循环自增数字.<br>
	 * 1000000-8000000(可能大于该值).预留200W，尽量确保不会超过7位数字。
	 * @return id字符串
	 */
	public String get() {
		String date = JodaTimeUtils.format(format);
		int sequence = INTEGER.getAndIncrement();
		if (sequence > safetyValve) { // 这里应该怎么优化
			INTEGER.set(start);
		}
		if (prefix != null) {
			return prefix + date + sequence;
		}
		return date + sequence;
	}
	
	/**
	 * 获取可变长度的id。格式是yyyyMMddHHmmssSSS + 自增数字.<br>
	 * 1-Integer.MAX_VALUE = 2147483647(可能大于该值)
	 * @return id字符串
	 */
	public String getId() {
		String date = JodaTimeUtils.format(format);
		int sequence = INTEGER.getAndIncrement();
		if (sequence > Integer.MAX_VALUE) { // 这里应该怎么优化
			INTEGER.set(start);
		}
		if (prefix != null) {
			return prefix + date + sequence;
		}
		return date + sequence;
	}

	public String getFormat() {
		return format;
	}

	public void setFormat(String format) {
		this.format = format;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public int getSafetyValve() {
		return safetyValve;
	}

	public void setSafetyValve(int safetyValve) {
		this.safetyValve = safetyValve;
	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		INTEGER.set(ID_START);
	}
}
